package org.dawn.deveco.plugin.resourceeditor.viewmodel;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.dawn.deveco.plugin.resourceeditor.common.Constants;
import org.dawn.deveco.plugin.resourceeditor.model.ColorResourceContent;
import org.dawn.deveco.plugin.resourceeditor.model.MediaResourceContent;
import org.dawn.deveco.plugin.resourceeditor.model.SimpleResourceContent;
import org.dawn.deveco.plugin.resourceeditor.model.interfaces.ResourceContent;
import org.dawn.deveco.plugin.resourceeditor.model.item.BaseItem;
import org.dawn.deveco.plugin.resourceeditor.model.item.MediaItem;
import org.dawn.deveco.plugin.resourceeditor.model.item.SimpleItem;
import org.dawn.deveco.plugin.resourceeditor.utils.Logger;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class ResourceFileHelper {
    private static final Logger LOG = Logger.getInstance(ResourceFileHelper.class);

    public ResourceContent loadResource(String category) {
        String path = Constants.RESOURCE_PATH_MAP.get(category);
        ResourceContent result;
        if (Constants.MEDIA_CATEGORY.equals(category)) {
            result = getTableContentOfMedia(path);
        } else {
            result = getTableContent(path, category);
        }
        result.setCategory(category);
        return result;
    }

    private ResourceContent getTableContentOfMedia(String path) {
        Path mediaPath = Paths.get(Constants.RESOURCE_ROOT_PATH, path);
        MediaResourceContent resourceContent = new MediaResourceContent();

        try (Stream<Path> list = Files.list(mediaPath)) {
            List<Path> mediaFiles = list.filter(Files::isRegularFile).collect(Collectors.toList());
            if (!mediaFiles.isEmpty()) {
                List<BaseItem> mediaItemList = new ArrayList<>();
                mediaFiles.forEach(p -> {
                    MediaItem mediaItem = new MediaItem();
                    mediaItem.setFullFileName(p.toFile().getAbsolutePath());
                    mediaItem.setFileName(p.toFile().getName());
                    mediaItem.setName(p.toFile().getName().replaceAll("\\..+$", ""));
                    mediaItemList.add(mediaItem);
                });
                resourceContent.addGroupData(ResourceContent.DEFAULT_GROUP, mediaItemList);
            }
        } catch (IOException e) {
            String msg = "加载media资源文件错误，资源目录：" + mediaPath;
            ResourceContent.LoadingState state = ResourceContent.LoadingState.FAILED_LOAD_IMAGE_FILE;
            state.setMessage(msg);
            resourceContent.setLoadingState(state);
            LOG.error(msg, e);
        }
        return resourceContent;
    }

    private ResourceContent getTableContent(String path, String category) {
        SimpleResourceContent resourceContent = new SimpleResourceContent();
        File file = Paths.get(Constants.RESOURCE_ROOT_PATH, path).toFile();
        if (!file.exists()) {
            ResourceContent.LoadingState state = ResourceContent.LoadingState.NO_MEDIA_FILE;
            state.setMessage(state.getMessage() + ": " + file.getAbsolutePath());
            resourceContent.setLoadingState(state);
            return resourceContent;
        }

        if ("color".equalsIgnoreCase(category)) {
            resourceContent = new ColorResourceContent();
        }

        try {
            ObjectMapper mapper = new ObjectMapper();
            Map<String, List<SimpleItem>> jsonMap = mapper.readValue(file, new TypeReference<>() {});
            for (Map.Entry<String, List<SimpleItem>> item: jsonMap.entrySet()) {
                resourceContent.addGroupData(item.getKey(), item.getValue());
            }
        } catch (Exception e) {
            String msg = "加载资源文件错误，资源文件：" + file.getAbsolutePath();
            ResourceContent.LoadingState state = ResourceContent.LoadingState.INVALID_MEDIA_FILE;
            state.setMessage(msg);
            resourceContent.setLoadingState(state);
            LOG.error(msg, e);
        }
        return resourceContent;
    }
}
